﻿//TODO: Threshold, Test

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Threshold
    /// </summary>
    public class Threshold : BaseForeBackgroundColorFilter
    {
        /// <summary>
        /// This is the common threshold
        /// </summary>
        protected byte m_nThreshold = 50;

        /// <summary>
        /// Initialize
        /// </summary>
        public Threshold()
        {
            this.M_PROCESSING_MODE = PROCESSING_MODE.Color;
        }

        /// <summary>
        /// Initialize and set threshold
        /// </summary>
        /// <param name="_nThreshold"></param>
        public Threshold(byte _nThreshold)
            : this()
        {
            m_nThreshold = _nThreshold;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_threshold"></param>
        internal Threshold(Threshold _threshold)
        {
            this.m_nThreshold = _threshold.m_nThreshold;
        }

        /// <summary>
        /// Sets or returns threshold
        /// </summary>
        public byte ThresholdValue
        {
            get { return m_nThreshold; }
            set { m_nThreshold = value; }
        }

        /// <summary>
        /// Execute this filter. This accepts a threshold from 0 to 100
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            ColorCalculation calc = Definitions.ColorCalculationDictionaryProcessingMode[M_PROCESSING_MODE];

            if (M_PROCESSING_MODE == PROCESSING_MODE.Color)
            {
                if (m_nThreshold < 0 || m_nThreshold > 100)
                {
                    throw new ArgumentException("Treshold value range 0 - 100");
                }
            }

            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;

            //Where does this come from? This are the percents
            //so 0x00028f5c*100 should be almost 0xFFFFFF or even 0x1000000
            int n1Percent = 0x00028f5c;      
            Color color = Color.Transparent;
            Color colorToSet = Color.Transparent;
            Color colorWhite = Definitions.White;
            Color colorBlack = Definitions.Black;

            int x = 0;
            int y = 0;

            float fValue = 0.0f;
            int nCalculatedThreshold = n1Percent * m_nThreshold;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap.GetPixel(x, y);
                    //TODO: This should not be needed here...
                    if (M_PROCESSING_MODE == PROCESSING_MODE.Color)
                    {
                        fValue = ColorFunctions.ToIntRGB(_bitmap.GetPixel(x, y));
                    }
                    else
                    {
                        fValue = calc(color);
                    }
                    _bitmap.SetPixel(x, y, fValue > nCalculatedThreshold ? m_ColorForeground : m_ColorBackground);                  
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// Calculate a Threshold Selection
        /// This might be repeated until convergence is reached
        /// </summary>
        public int GetThreshold(UnsafeBitmap _bitmap)
        {
            int nThreshold = new Random(DateTime.Now.Millisecond).Next(0, 255);
            int x = 0;
            int y = 0;

            int nG1 = 0;
            int nG1Count = 0;

            int nG2 = 0;
            int nG2Count = 0;

            int nValue = 0;

            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    nValue = _bitmap.GetGrayPixelValue(x, y);
                    if (nValue > nThreshold)
                    {
                        nG1 += nValue;
                        nG1Count++;
                    }
                    else
                    {
                        nG2 += nValue;
                        nG2Count++;
                    }
                }
            }
            if (nG1Count == 0) nG1Count = 1;
            if (nG2Count == 0) nG2Count = 1;
            int nM1 = nG1 / nG1Count;
            int nM2 = nG2 / nG2Count;
            nThreshold = (nM1 + nM2) / 2;
            return nThreshold;
        }

        /// <summary>
        /// use this to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Threshold(this);
        }
    }
}
